/**
 * Copyright (C) 2013-2014 the original author or authors.
 */
package com.foreveross.bsl.apns;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.Proxy;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.notnoop.apns.APNS;
import com.notnoop.apns.ApnsDelegate;
import com.notnoop.apns.ApnsNotification;
import com.notnoop.apns.ApnsService;
import com.notnoop.apns.ApnsServiceBuilder;
import com.notnoop.apns.DeliveryError;

/**
 * xxx
 * 
 * @author Wangyi
 * @version v1.0
 * 
 * @date 2013-11-20
 * 
 */
public class CertApnsService {

	private final static Logger log = LoggerFactory.getLogger(CertApnsService.class);

	private ApnsService apns;
	
	private int nSent=0, nFailed=0;

	public CertApnsService(String certFilename, String certPassword, Proxy proxy, boolean sandbox) throws IOException {
		File certFile = new File(System.getProperty("user.dir") + "/apns/" + certFilename);
		log.info("cert file:{} exist? {}", certFile, certFile.exists());
		InputStream certIs = new FileInputStream(certFile);
		try {
			ApnsServiceBuilder asb = APNS.newService().withCert(certIs, certPassword).withDelegate(new ApnsLogDelegate());
			if (sandbox) {
				asb.withSandboxDestination();
			} else {
				asb.withProductionDestination();
			}
			if (proxy != null) {
				asb.withProxy(proxy);
			}
			apns = asb.build();
		} finally {
			if (certIs != null) {
				certIs.close();
			}
		}
	}

	public void send(String token, String msg) throws IOException {
		this.send(new String[] { token }, msg, 1);
	}

	public void send(String token, String msg, int repeat) throws IOException {
		this.send(new String[] { token }, msg, repeat);
	}

	public void send(String[] tokens, String msg) throws IOException {
		this.send(tokens, msg, 1);
	}

	public void send(String[] tokens, String msg, int repeat) throws IOException {
		for (int i = 1; i <= repeat; i++) {
			Collection<String> tokenList = Arrays.asList(tokens);
			apns.push(tokenList, getDefaultPayload(i+ " " + msg ));
			if (repeat > 1) {
				try {
					Thread.sleep(1500);
				} catch (InterruptedException e) {
				}
			}
		}
	}

	private String getDefaultPayload(String msg) {
		SimpleDateFormat sdf = new SimpleDateFormat("MM-dd HH:mm:ss");
		msg = msg + " " + sdf.format(new Date());
		return APNS.newPayload().alertBody(msg).badge(1).sound("default").build();
	}
	
	public int getTotalSent(){
		return nSent-nFailed;
	}
	
	public int getTotalFailed(){
		return nFailed;
	}
	
	public int getTotalCount(){
		return nSent+nFailed;
	}
	
	public void clearCount(){
		this.nSent=0;
		this.nFailed=0;
	}
	
	class ApnsLogDelegate implements ApnsDelegate {

		@Override
		public void messageSent(ApnsNotification message, boolean resent) {
			nSent++;
			log.debug("messageSent() msg: {}, resent: {}", message, resent);
		}

		@Override
		public void messageSendFailed(ApnsNotification message, Throwable e) {
			nFailed++;
			log.error("messageSendFailed() msg: " + message, e);
		}

		@Override
		public void connectionClosed(DeliveryError e, int messageIdentifier) {
			log.error("connectionClosed() e:{}, msgId:{}", e, messageIdentifier);
		}

		@Override
		public void cacheLengthExceeded(int newCacheLength) {
			log.debug("cacheLengthExceeded() new cache length:{}",
					newCacheLength);
		}

		@Override
		public void notificationsResent(int resendCount) {
			log.debug("notificationsResent() resendCount:{}", resendCount);
		}

	}
}
